package com.bc.plugin.doc.resolver;

import com.power.common.util.CollectionUtil;
import com.power.common.util.StringUtil;
import com.power.doc.model.ApiDataDictionary;
import com.power.doc.model.ApiDocDict;
import com.power.doc.model.DataDict;
import com.power.doc.utils.DocClassUtil;
import com.thoughtworks.qdox.JavaProjectBuilder;
import com.thoughtworks.qdox.model.JavaClass;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

public class DictionaryResolver {
    /**
     * Build dictionary
     *
     * @param apiDataDictionaryList apiDataDictionary List
     * @return list of ApiDocDict
     */
    public static List<ApiDocDict> buildDictionary(List<ApiDataDictionary> apiDataDictionaryList, JavaProjectBuilder javaProjectBuilder) {
        if (CollectionUtil.isEmpty(apiDataDictionaryList)) {
            return new ArrayList<>(0);
        }
        List<ApiDocDict> apiDocDictList = new ArrayList<>();
        try {
            int order = 0;
            for (ApiDataDictionary apiDataDictionary : apiDataDictionaryList) {
                order++;
                ApiDocDict apiDocDict = new ApiDocDict();
                apiDocDict.setOrder(order);
                Class<? extends Enum> clazz = apiDataDictionary.getEnumClass();
                if (Objects.isNull(clazz)) {
                    throw new RuntimeException(" enum class name can't be null.");
                }
                apiDocDict.setTitle(apiDataDictionary.getTitle());
                JavaClass javaClass = javaProjectBuilder.getClassByName(clazz.getCanonicalName());
                if (apiDataDictionary.getTitle() == null) {
                    apiDocDict.setTitle(javaClass.getComment());
                }

                List<DataDict> dataDictList = new ArrayList<>();
                Enum[] objects = clazz.getEnumConstants();
                Method valueMethod = null;
                Method descMethod = null;
                if (apiDataDictionary.getCodeField() != null) {
                    String valueMethodName = "get" + StringUtil.firstToUpperCase(apiDataDictionary.getCodeField());
                    valueMethod = clazz.getMethod(valueMethodName);
                }
                if (apiDataDictionary.getDescField() != null) {
                    String descMethodName = "get" + StringUtil.firstToUpperCase(apiDataDictionary.getDescField());
                    descMethod = clazz.getMethod(descMethodName);
                }

                for (Enum object : objects) {
                    Object val;
                    if (valueMethod != null) {
                        val = valueMethod.invoke(object);
                    } else {
                        val = object.name();
                    }

                    Object desc;
                    if (descMethod != null) {
                        desc = descMethod.invoke(object);
                    } else {
                        desc = javaClass.getFieldByName(object.name()).getComment();
                    }
                    String processedType = DocClassUtil.processTypeNameForParams(val.getClass().getCanonicalName());
                    DataDict dataDict = new DataDict();
                    dataDict.setType(processedType);
                    dataDict.setDesc(String.valueOf(desc));
                    dataDict.setValue(String.valueOf(val));
                    dataDictList.add(dataDict);
                }
                apiDocDict.setDataDictList(dataDictList);
                apiDocDictList.add(apiDocDict);
            }
        } catch (NoSuchMethodException | InvocationTargetException | IllegalAccessException e) {
            e.printStackTrace();
        }
        return apiDocDictList;
    }
}
